﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.DirectX.Direct3D;
using DXFont = Microsoft.DirectX.Direct3D.Font;
using Font = System.Drawing.Font;
using Color = System.Drawing.Color;
using System.Reflection;
using System.Drawing;
using Microsoft.DirectX;

namespace KGFontOpr
{
    public static class Expand
    {
        unsafe public static Device ConvertDevice(this GraphicsDevice xnaDevice)
        {
            IntPtr ptr = IntPtr.Zero;

            Pointer privateField = GetPrivateField<GraphicsDevice, Pointer>(xnaDevice, "pComPtr");
            ptr = new IntPtr(Pointer.Unbox(privateField));

            return new Device(ptr);
        }

        private static U GetPrivateField<T, U>(T obj, string fieldName)
        {
            return (U)typeof(T).GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance).GetValue(obj);
        }  
    }

    public class FontOpr:IDisposable
    {
        static public List<FontOpr> FontList = new List<FontOpr>();
        public Font font = null;
        public DXFont DxFont = null;
        public GraphicsDevice XnaDevice = null;
        public Device DxDevice = null;
        /*
        public FontOpr(Device device, string name, int size)
            :this(device,new Font(name,size,GraphicsUnit.Pixel))
        {

        } 
        public FontOpr(Device device, Font winfont)
        {
            font = winfont; 
            DxDevice = device;
            DxFont = new DXFont(DxDevice, font);
        } 
        */

        public static void Release()
        {
            for (int i = 0; i < FontList.Count; i++)
            {
                if (FontList[i] != null)
                {
                    FontList[i].DxFont.Dispose();
                    FontList[i] = null;
                }
            }
            FontList.Clear();
        }
        public void Reset(Font winfont)
        {
            if (winfont.Name != font.Name || winfont.Size != font.Size)
            {
                font = winfont;

                if (DxFont != null)
                    Dispose();

                DxFont = new DXFont(DxDevice, font);
                FontList.Add(this);
            }
        }
        public FontOpr(GraphicsDevice device, string name, int size)
            :this(device,new Font(name,size,GraphicsUnit.Pixel))
        {

        } 
        public FontOpr(GraphicsDevice device, Font winfont)
        {
            font = winfont;
            XnaDevice = device;
            DxDevice = device.ConvertDevice();
            DxFont = new DXFont(DxDevice, font);
            FontList.Add(this);
        }
        public void DrawString(string text, Point pos, Color color)
        {
            DxFont.DrawText(null, text, pos, color);
        }

        public void DrawString(string text, int x, int y, Color color)
        {
            DxFont.DrawText(null, text, x, y, color);
        }

        public void DrawString(string text, Rectangle rect, Color color, KGDrawTextFormat drawTextFormat = KGDrawTextFormat.VerticalCenter | KGDrawTextFormat.Center| KGDrawTextFormat.WordBreak)
        {
            DxFont.DrawText(null, text, rect, (DrawTextFormat)drawTextFormat, color);
        }

        public Rectangle MeasureString(string text, Color color, KGDrawTextFormat drawTextFormat = KGDrawTextFormat.VerticalCenter | KGDrawTextFormat.Center| KGDrawTextFormat.WordBreak)
        {
            return DxFont.MeasureString(null, text, (DrawTextFormat)drawTextFormat, color);
        }

        public void Dispose()
        {
            DxFont.Dispose();
            FontList.Remove(this);
        }
    }
    public enum KGDrawTextFormat
    {
        Left = 0,
        None = 0,
        Top = 0,
        Center = 1,
        Right = 2,
        VerticalCenter = 4,
        Bottom = 8,
        WordBreak = 16,
        SingleLine = 32,
        ExpandTabs = 64,
        NoClip = 256,
        RightToLeftReading = 131072,
    }
}
